package com.fingard.dsp.bank.directbank.ccb02;

import com.fingard.constant.Format;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.IForeignCurrency;
import com.fingard.dsp.bank.reqrespobj.foreigncurrsingle.ReqForeignCurrSingle;
import com.fingard.dsp.bank.reqrespobj.foreigncurrsingle.ReqQryForeignCurrSingle;
import com.fingard.dsp.bank.reqrespobj.foreigncurrsingle.RetAtsForeignCurrSingle;
import com.fingard.dsp.bank.reqrespobj.foreigncurrsingle.detail.RetAtsForeignCurrPayDetail;
import com.fingard.net.ConnState;
import com.fingard.text.StringHelper;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

import java.util.Date;

public class CCB02ForeignCurrSinglePay extends CCB02Base implements IForeignCurrency {
    /**
     * 外汇单笔支付
     *
     * @param reqForeignCurrSingle
     * @return
     * @throws Exception
     */
    @Override
    public RetAtsForeignCurrSingle foreignCurrPay(ReqForeignCurrSingle reqForeignCurrSingle) throws Exception {
        RetAtsForeignCurrSingle retAts = new RetAtsForeignCurrSingle(reqForeignCurrSingle.reqHeader);
        RetAtsForeignCurrPayDetail tmpRetDetail = null;
        if ("DomesticFCP".equals(reqForeignCurrSingle.reqHeader.transType) || "CrossborderFCP".equals(reqForeignCurrSingle.reqHeader.transType)) {
            tmpRetDetail = NW3401(reqForeignCurrSingle);
        } else {
            tmpRetDetail = new RetAtsForeignCurrPayDetail();
            tmpRetDetail.respCode = "-1";
            tmpRetDetail.respInfo = "未知的业务类型：" + reqForeignCurrSingle.reqHeader.transType;
        }
        retAts.writeRetDetail(tmpRetDetail);
        return retAts;
    }

    private RetAtsForeignCurrPayDetail NW3401(ReqForeignCurrSingle reqForeignCurrSingle) throws Exception {
        RetAtsForeignCurrPayDetail detail = new RetAtsForeignCurrPayDetail();
        try {
            CCB02Header bankHeader = new CCB02Header();
            bankHeader.REQUEST_SN = codeToAscii(reqForeignCurrSingle.singleDetail.askNumber);
            bankHeader.TX_CODE = "NW3401";

            XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
            xmlWriter.autoFormat = false;//报文串需要整个字符串传送，中间需无回车符，否则会签名出错
            writeCommonHeader(xmlWriter, bankHeader);

            xmlWriter.writeStartElement("TX_INFO");
            xmlWriter.writeElementString("CstPty_TxnSrlNo", reqForeignCurrSingle.singleDetail.askNumber);//客户方交易流水号
            xmlWriter.writeElementString("StlMe_Cd", "08");//结算方式代码 08-电汇
            xmlWriter.writeElementString("MsgRp_Prty_Cd", reqForeignCurrSingle.singleDetail.paySpd.equals("0") ? "01" : "02");//发电等级 01-普通,02-加急
            xmlWriter.writeElementString("FrnCy_Py_Obj_Cd", reqForeignCurrSingle.singleDetail.isDomestic.equals("1") ? "02" : "03");//汇款类型 02-国内他行,03-国外他行
            xmlWriter.writeElementString("CshEx_Cd", "");//？？？钞汇代码 1-钞，2-汇
            xmlWriter.writeElementString("Rmt_Psn_Nm", reqForeignCurrSingle.singleDetail.payName);//汇款人名称 汇款人名称+汇款人地址长度和不能大于132，境外汇款不得有中文
            xmlWriter.writeElementString("Rmt_Psn_Adr", reqForeignCurrSingle.singleDetail.payAddr);//汇款人地址 可空 汇款人名称+汇款人地址长度和不能大于132，境外汇款不得有中文
            xmlWriter.writeElementString("Exg_AccNo", reqForeignCurrSingle.singleDetail.payCashAct);//汇款账号
            xmlWriter.writeElementString("Rmt_CcyCd", convertCurToBank(reqForeignCurrSingle.singleDetail.payCur));//汇款币种
            xmlWriter.writeElementString("FrnCy_Py_Rmt_Amt", reqForeignCurrSingle.singleDetail.payCashAmount);//汇款金额
            xmlWriter.writeElementString("ValDt", Format.Date8Format.format(new Date()));//起息日 格式YYYYMMDD
            xmlWriter.writeElementString("RcvPymtPs_Nm", reqForeignCurrSingle.singleDetail.recName);//收款人名称 收款人名称+收款人地址长度和不能大于132，境外汇款不得有中文
            xmlWriter.writeElementString("RcvPymtPs_Adr", reqForeignCurrSingle.singleDetail.recAddr);//收款人地址 收款人名称+收款人地址长度和不能大于132，境外汇款不得有中文
            xmlWriter.writeElementString("FrnCy_RcvPymtPs_AccNo", reqForeignCurrSingle.singleDetail.recAct);//收款人账号
            xmlWriter.writeElementString("RPPDBnkSWIFT_Cd", reqForeignCurrSingle.singleDetail.recSWIFTCODE);//收款人开户行SWIFTCODE
            xmlWriter.writeElementString("RPPDBnk_Nm", "");//收款人开户行名称 收款人开户行名称、地址、swiftcode三者有一项必输
            xmlWriter.writeElementString("RPPDBnk_Adr", "");//收款人开户行地址 收款人开户行名称、地址、swiftcode三者有一项必输
            xmlWriter.writeElementString("RPPDBnk_AccNo", "");//收款人开户行账号 可空
            xmlWriter.writeElementString("RPPDBnk_AgncBnk_AccNo", reqForeignCurrSingle.singleDetail.recAgentBnkAct);//收款人开户行在其代理行账号 可空
            xmlWriter.writeElementString("RcvPymtPs_RtCtyRgn_Cd", reqForeignCurrSingle.singleDetail.recCountryCode);//收款人常驻国家(地区)代码
            xmlWriter.writeElementString("RcvPymtPs_Rsdt_Cty_Nm", "");//收款人常驻国家(地区)名称 可空
            xmlWriter.writeElementString("RPyBk_AgncBnk_Nm", reqForeignCurrSingle.singleDetail.recAgentBnkName);//收款银行代理行名称 可空 收款银行代理行名称+收款银行代理行地址长度和不能大于132，境外汇款不得有中文
            xmlWriter.writeElementString("RPyBk_AgncBnk_Adr", reqForeignCurrSingle.singleDetail.recAgentBnkAddr);//收款银行代理行地址 可空
            xmlWriter.writeElementString("RPyBk_AgncBnkSWIFT_Cd", reqForeignCurrSingle.singleDetail.recAgentBnkSWIFT);//收款银行代理行SWIFTCODE 可空
            //付款类型 01-预付货款02-货到付款03-退款04-其他
            if (reqForeignCurrSingle.singleDetail.payMethod.equals("A")) {
                xmlWriter.writeElementString("Py_Char_Cd", "01");
            } else if (reqForeignCurrSingle.singleDetail.payMethod.equals("P")) {
                xmlWriter.writeElementString("Py_Char_Cd", "02");
            } else if (reqForeignCurrSingle.singleDetail.payMethod.equals("R")) {
                xmlWriter.writeElementString("Py_Char_Cd", "03");
            } else if (reqForeignCurrSingle.singleDetail.payMethod.equals("O")) {
                xmlWriter.writeElementString("Py_Char_Cd", "04");
            }
            xmlWriter.writeElementString("DlTax_GdItm_Py_Ind", reqForeignCurrSingle.singleDetail.isBondedGood);//本笔款项是否为保税货物项下 1-是，0-否
            xmlWriter.writeElementString("DstAbrdCst_ChrgTo_Cd", reqForeignCurrSingle.singleDetail.costMode);//国内外费用承担标志 0-汇款人OUR,2-收款人BEN,3-共同SHA
            xmlWriter.writeElementString("Cmsn_ChrgFee_AccNo", "");//收费账号 可空
            xmlWriter.writeElementString("Cost_CcyCd", "");//收费币种 可空
            xmlWriter.writeElementString("Rmt_Pstcrpt", reqForeignCurrSingle.singleDetail.abstractATS);//汇款附言(存对账码) 境外汇款不得有中文
            xmlWriter.writeElementString("Rmt_Rmrk", reqForeignCurrSingle.singleDetail.purpose);//备注(存用途)
            xmlWriter.writeElementString("Itnl_IcmEpd_Txn_ECD_1", reqForeignCurrSingle.singleDetail.transCode1);//交易编码1 六位编码
            xmlWriter.writeElementString("Crspd_CcyCd_1", convertCurToBank(reqForeignCurrSingle.singleDetail.currency1));//相应币种1 交易编码1有值时必输,
            xmlWriter.writeElementString("Crspd_Amt_1", reqForeignCurrSingle.singleDetail.amout1);//相应金额1 交易编码1有值时必输 相应金额1与相应金额2之和等于汇款金额
            xmlWriter.writeElementString("Txn_Pstcrpt_1", reqForeignCurrSingle.singleDetail.postScript1);//交易附言1 交易编码1有值时必输
            xmlWriter.writeElementString("Itnl_IcmEpd_Txn_ECD_2", reqForeignCurrSingle.singleDetail.transCode2);//交易编码2
            xmlWriter.writeElementString("Crspd_CcyCd_2", convertCurToBank(reqForeignCurrSingle.singleDetail.currency2));//相应币种2
            xmlWriter.writeElementString("Crspd_Amt_2", reqForeignCurrSingle.singleDetail.amout2);//相应金额2
            xmlWriter.writeElementString("Txn_Pstcrpt_2", reqForeignCurrSingle.singleDetail.postScript2);//交易附言2
            xmlWriter.writeElementString("Fil_Psn_Nm", reqForeignCurrSingle.singleDetail.contactPerson);//填报人姓名 必输
            xmlWriter.writeElementString("Fil_Psn_Tel", reqForeignCurrSingle.singleDetail.contactNum);//填报人电话 必输
            //付汇性质 汇款类型为境外时，付汇性质非必输，境内汇出时使用:01-保税区,02-出口加工区,03-钻石交易所,04-离岸账户深加工结转,05-其他特殊经济区域,06-其他境内汇出时使用
            if (reqForeignCurrSingle.singleDetail.payProperty.equals("X")) {
                xmlWriter.writeElementString("Pymt_Char_Cd", "01");
            } else if (reqForeignCurrSingle.singleDetail.payProperty.equals("E")) {
                xmlWriter.writeElementString("Pymt_Char_Cd", "02");
            } else if (reqForeignCurrSingle.singleDetail.payProperty.equals("D")) {
                xmlWriter.writeElementString("Pymt_Char_Cd", "03");
            } else if (reqForeignCurrSingle.singleDetail.payProperty.equals("A")) {
                xmlWriter.writeElementString("Pymt_Char_Cd", "05");
            } else if (reqForeignCurrSingle.singleDetail.payProperty.equals("M")) {
                xmlWriter.writeElementString("Pymt_Char_Cd", "04");
            } else if (reqForeignCurrSingle.singleDetail.payProperty.equals("O")) {
                xmlWriter.writeElementString("Pymt_Char_Cd", "06");
            }
            xmlWriter.writeElementString("AtLst_ShDt", "");//最迟装运日期 可空 格式YYYYMMDD
            xmlWriter.writeElementString("Fx_Rmt_Ctr_No", reqForeignCurrSingle.singleDetail.contractNo);//合同号
            xmlWriter.writeElementString("Inv_ID", reqForeignCurrSingle.singleDetail.invoiceNo);//发票号
            xmlWriter.writeElementString("ExOff_ADNum", reqForeignCurrSingle.singleDetail.businessNum);//外汇局批件/备案表号
            xmlWriter.writeElementString("Dcl_Bl_Oprt_UnCd", "");//报关单经营单位代码
            xmlWriter.writeElementString("PrpyPymFrGsOcpCtrPctg", "");//预付货款占合同比例 跨境人民币付款时可输入
            xmlWriter.writeElementString("Dcln_Frcst_Dys", "");//报关预计天数 跨境人民币付款时可输入
            xmlWriter.writeElementString("Dcln_RcvPy_TpCd", "");//报关收付类型代码 跨境人民币付款时可输入1：人民币报关—人民币结算3：外币报关—人民币结算
            xmlWriter.writeElementString("Com_Trd_Amt", "");//一般贸易金额 跨境人民币付款时可输入
            xmlWriter.writeElementString("ChgIn_Pcs_Amt", "");//进料加工金额 跨境人民币付款时可输入
            xmlWriter.writeElementString("Othr_Trd_Amt", "");//其他贸易金额 跨境人民币付款时可输入
            xmlWriter.writeElementString("Brdr_Trd_Amt", "");//边境贸易金额 跨境人民币付款时可输入
            xmlWriter.writeElementString("Dcln_Unit_Nm", "");//报关单位名称 跨境人民币付款时可输入
            xmlWriter.writeElementString("OrCd", "");//报关经营单位组织机构代码 跨境人民币付款时可输入
            xmlWriter.writeElementString("XBdPy_Bsn_ID", "");//跨境电商订单编号 可空
            xmlWriter.writeElementString("Rvl_Rcrd_Num", "0");//报关单条数 若无报关单信息，则送0
            xmlWriter.writeElementString("SIGN_INFO", "");//？？？签名信息
            xmlWriter.writeElementString("SIGNCERT", "");//签名CA信息 客户采用socket连接时，建行客户端自动添加
            xmlWriter.writeEndDocument();

            String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());//发送银行
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    detail.respCode = "0";
                    detail.reqSeqID = reqForeignCurrSingle.singleDetail.askNumber;//tmpBkReader.getFirstText("/TX/REQUEST_SN");
                    String RETURN_CODE = tmpBkReader.getFirstText("/TX/RETURN_CODE");
                    String RETURN_MSG = tmpBkReader.getFirstText("/TX/RETURN_MSG");
                    if (RETURN_CODE.equals("000000")) {
                        String Rslt_Cd = tmpBkReader.getFirstText("/TX/TX_INFO/CshMgt_Txn_Rslt_Cd");//1-交易成功 2-交易失败 3-银行处理中 e-银行退
                        String Err_Inf = tmpBkReader.getFirstText("/TX/TX_INFO/Err_Inf");
                        detail.respInfo = StringHelper.joinNotEmpty(";", "响应信息：" + RETURN_MSG, "交易结果代码：" + Rslt_Cd + ";交易信息：" + Err_Inf);
                        detail.transState = RETURN_CODE + "+" + Rslt_Cd;
                        detail.payInfoCode = detail.transState;
                    } else {
                        detail.respInfo = RETURN_MSG;
                        detail.transState = RETURN_CODE;
                        detail.payInfoCode = detail.transState;
                    }
                } else {
                    detail.respCode = "-1";
                    detail.respInfo = tmpSbMsg.toString();
                }
            } else if (tmpStrRet[0].equals(ConnState.FAIL)) {
                detail.respCode = "0";
                detail.respInfo = tmpStrRet[1];
                detail.reqSeqID = reqForeignCurrSingle.singleDetail.askNumber;
                detail.transState = PaymentState.FAIL_Payment;
                detail.payInfoCode = tmpStrRet[0];
            } else {
                detail.respCode = "-1";
                detail.respInfo = tmpStrRet[1];
            }
        } catch (Exception e) {
            detail.respCode = "-1";
            detail.respInfo = "外币汇款出现异常!";
            WriteBankLogLn("外币汇款出现异常,异常信息:" + e.getMessage());
            e.printStackTrace();
        }

        return detail;
    }

    /**
     * 外汇单笔支付查询
     *
     * @param reqQryForeignCurrSingle
     * @return
     * @throws Exception
     */
    @Override
    public RetAtsForeignCurrSingle qryForeignCurrPay(ReqQryForeignCurrSingle reqQryForeignCurrSingle) throws Exception {
        RetAtsForeignCurrSingle retAts = new RetAtsForeignCurrSingle(reqQryForeignCurrSingle.reqHeader);
        RetAtsForeignCurrPayDetail tmpRetDetail = new RetAtsForeignCurrPayDetail();
        try {
            CCB02Header bankHeader = new CCB02Header();
            bankHeader.REQUEST_SN = codeToAscii(reqQryForeignCurrSingle.reqHeader.transSeqID);
            bankHeader.TX_CODE = "NW3402";

            XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
            xmlWriter.autoFormat = false;//报文串需要整个字符串传送，中间需无回车符，否则会签名出错
            writeCommonHeader(xmlWriter, bankHeader);

            xmlWriter.writeStartElement("TX_INFO");
            xmlWriter.writeElementString("CstPty_TxnSrlNo", reqQryForeignCurrSingle.askNumber);//客户方交易流水号
            xmlWriter.writeElementString("Btch_Dtl_ID", "");//批量明细编号 批量交易查批次内某一笔明细时必填
            xmlWriter.writeEndDocument();

            String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String RETURN_CODE = tmpBkReader.getFirstText("/TX/RETURN_CODE");
                    String RETURN_MSG = tmpBkReader.getFirstText("/TX/RETURN_MSG");
                    if (RETURN_CODE != null && RETURN_CODE.equals("000000")) {
                        String Rslt_Cd = tmpBkReader.getFirstText("/TX/TX_INFO/CshMgt_Txn_Rslt_Cd");//交易结果代码
                        String Err_Cd = tmpBkReader.getFirstText("/TX/TX_INFO/CshMgt_Err_Cd");//错误代码
                        String Err_Inf = tmpBkReader.getFirstText("/TX/TX_INFO/Err_Inf");//错误信息
                        tmpRetDetail.reqSeqID = reqQryForeignCurrSingle.askNumber;
                        tmpRetDetail.respCode = "0";
                        tmpRetDetail.respInfo = StringHelper.joinNotEmpty(";", "响应信息：" + RETURN_MSG, "错误代码：" + Err_Cd + ";错误信息：" + Err_Inf);
                        tmpRetDetail.transState = RETURN_CODE + "+" + Rslt_Cd;
                        tmpRetDetail.payInfoCode = tmpRetDetail.transState;
                    } else {
                        tmpRetDetail.reqSeqID = reqQryForeignCurrSingle.askNumber;
                        tmpRetDetail.respCode = "0";
                        tmpRetDetail.respInfo = RETURN_MSG;
                        tmpRetDetail.transState = RETURN_CODE;
                        tmpRetDetail.payInfoCode = tmpRetDetail.transState;
                    }
                } else {
                    tmpRetDetail.respCode = "-1";
                    tmpRetDetail.respInfo = tmpSbMsg.toString();
                }
            } else {
                tmpRetDetail.respCode = "-1";
                tmpRetDetail.respInfo = tmpStrRet[1];
            }
        } catch (Exception e) {
            tmpRetDetail.respCode = "-1";
            tmpRetDetail.respInfo = "汇出汇款申请查询，出现异常！";
            WriteBankLogLn("汇出汇款申请查询，出现异常,异常信息：" + e.getMessage());
            e.printStackTrace();
        }
        retAts.writeRetDetail(tmpRetDetail);
        return retAts;
    }
}
